package com.bristua.barcode.order.biz;

import com.bristua.barcode.common.bean.CustomerParams;
import com.bristua.barcode.common.constants.Constants;
import com.bristua.barcode.common.enums.CommonCode;
import com.bristua.barcode.common.exception.BizException;
import com.bristua.barcode.common.util.*;
import com.bristua.barcode.customer.dao.TCustomerBindSupplierMapper;
import com.bristua.barcode.customer.dao.TCustomerMapper;
import com.bristua.barcode.customer.enums.CustomerCode;
import com.bristua.barcode.customer.model.TCustomer;
import com.bristua.barcode.customer.model.TCustomerBindSupplier;
import com.bristua.barcode.customer.model.bo.CustomerBindQRCode;
import com.bristua.barcode.customer.model.condition.SendOrderParams;
import com.bristua.barcode.customer.model.condition.TCustomerBindSupplierExample;
import com.bristua.barcode.customer.model.condition.TCustomerExample;
import com.bristua.barcode.order.controller.SendOrderController;
import com.bristua.barcode.order.dao.TPayOrderMapper;
import com.bristua.barcode.order.enums.OrderCode;
import com.bristua.barcode.order.model.TPayOrder;
import com.bristua.barcode.order.model.condition.TPayOrderExample;
import com.bristua.barcode.order.model.vo.SendOrderSuccessVO;
import com.bristua.barcode.supplier.dao.TChannelMapper;
import com.bristua.barcode.supplier.dao.TQrCodeMapper;
import com.bristua.barcode.supplier.enums.SupplierCode;
import com.bristua.barcode.supplier.model.TChannel;
import com.bristua.barcode.supplier.model.TQrCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;


/**
 * Created by Administrator on 2019/8/1 0001.
 */
@Service
@Transactional
public class SendOrderBiz {

    private static final Logger logger = LoggerFactory.getLogger(SendOrderBiz.class);

    @Autowired
    private HttpSessionUtil httpSessionUtil;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private HandelRedisQueueUtil handelRedisQueueUtil;
    @Resource
    private TCustomerMapper tCustomerMapper;

    @Resource
    private TPayOrderMapper tPayOrderMapper;

    @Resource
    private TQrCodeMapper tQrCodeMapper;

    @Resource
    private TCustomerBindSupplierMapper tCustomerBindSupplierMapper;

    @Resource
    private TChannelMapper tChannelMapper;


    public SendOrderSuccessVO sendOrder(SendOrderParams sendOrderParams) {
        String goodsId = sendOrderParams.getGoodsId();
        TChannel tChannel = tChannelMapper.selectByPrimaryKey(goodsId);
        if (tChannel == null || tChannel.getStatus().intValue() == 0) {
            throw new BizException(OrderCode.NO_CONFIG_CHANNEL.getCode(), OrderCode.NO_CONFIG_CHANNEL.getMsg());
        }

        CustomerParams userInfo = httpSessionUtil.getUserInfo();
        StringBuilder sb = new StringBuilder();
        sb.append(userInfo.getAppId()).append(sendOrderParams.getOrderNo())
                .append(sendOrderParams.getTimestap()).append(sendOrderParams.getMoney())
                .append(userInfo.getKeyStore());
        String signStr = MD5Util.Bit32(sb.toString());

        if (!signStr.equals(sendOrderParams.getSign())) {
            logger.error("==>签名错误,客户端签名:" + sendOrderParams.getSign() + ",服务端签名:" + signStr);
            throw new BizException(CommonCode.SING_FAIL.getCode(), CommonCode.SING_FAIL.getMsg());
        }

        //判断商户是否存在
        String merchantId = userInfo.getMerchantId();
        TCustomerExample tCustomerExample = new TCustomerExample();
        tCustomerExample.createCriteria().andCustomerNoEqualTo(merchantId);
        List<TCustomer> tCustomersIsExists = tCustomerMapper.selectByExample(tCustomerExample);
        if (tCustomersIsExists == null || tCustomersIsExists.size() == 0) {
            throw new BizException(CustomerCode.CUSTOMER_IS_NOT_EXIST.getCode(), CustomerCode.CUSTOMER_IS_NOT_EXIST.getMsg());
        }

        TCustomer tCustomer = tCustomersIsExists.get(0);
        tCustomer.setAppId(userInfo.getAppId());
        tCustomer.setSecretKey(userInfo.getKeyStore());

        tCustomerMapper.updateByPrimaryKeySelective(tCustomer);

        //判断是否重复下单
        if (!StringUtils.isEmpty(redisTemplate.opsForValue().get(sendOrderParams.getOrderNo()))) {
            throw new BizException(OrderCode.RE_SNED_ORDER.getCode(), OrderCode.RE_SNED_ORDER.getMsg());
        } else {
            TPayOrderExample tPayOrderExample = new TPayOrderExample();
            tPayOrderExample.createCriteria().andCustomerOrderNoEqualTo(sendOrderParams.getOrderNo());
            List<TPayOrder> tPayOrders = tPayOrderMapper.selectByExample(tPayOrderExample);
            if (tPayOrders != null && tPayOrders.size() > 0) {
                throw new BizException(OrderCode.RE_SNED_ORDER.getCode(), OrderCode.RE_SNED_ORDER.getMsg());
            } else {
                redisTemplate.opsForValue().set(sendOrderParams.getOrderNo(), sendOrderParams.getOrderNo(), 30000, TimeUnit.SECONDS);//防止客户端重复订单,30秒过期
            }
        }

        List<String> qrcodeIds = new ArrayList<>();//需要被下架的二维码
        TCustomerExample tCustomerExample1 = new TCustomerExample();
        tCustomerExample1.createCriteria().andCustomerNoEqualTo(userInfo.getMerchantId());
        List<TCustomer> tCustomers = tCustomerMapper.selectByExample(tCustomerExample1);
        CustomerBindQRCode sendOrderData = null;
        if (tCustomers != null && tCustomers.size() > 0) {
            sendOrderData = getSendOrderData(tCustomers.get(0), sendOrderParams, userInfo, qrcodeIds);
            logger.info("==>得到的二维码数据:" + JsonUtil.toJson(sendOrderData));
            if (sendOrderData == null) {
                throw new BizException(OrderCode.SEND_ORDER_FAIL_QRCODE_NOT_FIND.getCode(), OrderCode.SEND_ORDER_FAIL_QRCODE_NOT_FIND.getMsg());
            }
            logger.info("==>开始下单.........");
            //开始创建订单
            TPayOrder tPayOrder = new TPayOrder();
            tPayOrder.setOrderId(SequenceUtil.nextId());
            tPayOrder.setCreateTime(DateUtils.getShowDateTime());
            tPayOrder.setCustomerNo(tCustomers.get(0).getCustomerNo());
            tPayOrder.setCustomerOrderNo(sendOrderParams.getOrderNo());
            tPayOrder.setPayStatus(1);
            tPayOrder.setPayAmt(sendOrderParams.getMoney());
            tPayOrder.setSupplierId(sendOrderData.getSupplierId());
            tPayOrder.setChannelId(sendOrderParams.getGoodsId());
            tPayOrder.setQrCodeId(sendOrderData.getQrCodeId());
            tPayOrderMapper.insert(tPayOrder);

            if (qrcodeIds.size() > 0) {
                asyncLowerShelfQrcode(qrcodeIds);
            }
            logger.info("==>正在将订单同步到redis集合中.........");
            //将订单同步redis集合中
            Calendar c = Calendar.getInstance();
            c.add(Calendar.MINUTE, 3);
            long timeInMillis = c.getTimeInMillis();
            redisTemplate.opsForSet().add(Constants.NO_PAY_ORDER_SET, tPayOrder.getOrderId() + "::" + timeInMillis);
//            redisTemplate.opsForHash().put(Constants.NO_PAY_ORDER_QUEUE,tPayOrder.getOrderId(),timeInMillis);
            SendOrderSuccessVO sendOrderSuccessVO = new SendOrderSuccessVO();
            sendOrderSuccessVO.setMerchantOrderNo(sendOrderParams.getOrderNo());
            sendOrderSuccessVO.setOrderNo(tPayOrder.getOrderId());
            sendOrderSuccessVO.setOrderAmt(sendOrderParams.getMoney() + "");
            return sendOrderSuccessVO;
        }
        return null;
    }

    private CustomerBindQRCode getSendOrderData(TCustomer tCustomer, SendOrderParams sendOrderParams, CustomerParams userInfo, List<String> qrcodeIds) {
        StringBuilder key = new StringBuilder();
        String goodsId = sendOrderParams.getGoodsId();
        key.append(tCustomer.getCustomerId()).append(goodsId);
        TChannel tChannel = tChannelMapper.selectByPrimaryKey(goodsId);
        if(tChannel.getChannelType().intValue()==1){
            key.append(sendOrderParams.getMoney());
        }
        String valueFromQueue = handelRedisQueueUtil.getValueFromQueue(key.toString());
        if (!StringUtils.isEmpty(valueFromQueue)) {
            CustomerBindQRCode customerBindQRCode = JsonUtil.json2Object(valueFromQueue, CustomerBindQRCode.class);
            BigDecimal add = new BigDecimal(sendOrderParams.getMoney()).add(new BigDecimal(customerBindQRCode.getFlowTotalAmt()));
            int i = add.compareTo(new BigDecimal(customerBindQRCode.getLimitAmt()));
            if (i < 0) {
                TQrCode tQrCode = tQrCodeMapper.selectByPrimaryKey(customerBindQRCode.getQrCodeId());
                if (tQrCode.getStatus().intValue() == 1 && tQrCode.getIsBind().intValue() == 1) {
                    TCustomerBindSupplierExample tCustomerBindSupplierExample = new TCustomerBindSupplierExample();
                    tCustomerBindSupplierExample.createCriteria().andCustomerIdEqualTo(tCustomer.getCustomerId()).andQrCodeIdEqualTo(tQrCode.getQrCodeId());
                    List<TCustomerBindSupplier> tCustomerBindSuppliers = tCustomerBindSupplierMapper.selectByExample(tCustomerBindSupplierExample);
                    if (tCustomerBindSuppliers != null && tCustomerBindSuppliers.size() > 0) {
                        //开始下单
                        return customerBindQRCode;
                    } else {
                        getSendOrderData(tCustomer, sendOrderParams, userInfo, qrcodeIds);
                    }

                } else {
                    getSendOrderData(tCustomer, sendOrderParams, userInfo, qrcodeIds);
                }

            } else {
                qrcodeIds.add(customerBindQRCode.getQrCodeId());
                getSendOrderData(tCustomer, sendOrderParams, userInfo, qrcodeIds);
            }
        } else {
            return null;
        }
        return null;
    }

    public static void main(String[] args) {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MINUTE, 2);
        long timeInMillis = c.getTimeInMillis();
        Date time = c.getTime();
        System.out.println(time);
    }

    /**
     * 异步下架二维码
     */
    @Async
    public void asyncLowerShelfQrcode(List<String> qrcodeIds) {
        logger.info("==>正在将这些二维码下架:" + JsonUtil.toJson(qrcodeIds));
        List<TQrCode> tQrCodeList = new ArrayList<>();
        for (String id : qrcodeIds) {
            TQrCode tQrCode = new TQrCode();
            tQrCode.setQrCodeId(id);
            tQrCode.setStatus(0);
            tQrCodeList.add(tQrCode);
        }
        tQrCodeMapper.batchUpdate(tQrCodeList);

    }

}
